package org.flycloud.web.decoupling;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;

import org.flycloud.web.decoupling.annotation.ReturnList;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.SessionAttribute;

import com.alibaba.fastjson.JSON;


public class ControllerProxy implements InvocationHandler {

	private String point;
	private Class<?> cls;

	public ControllerProxy(String point, Class<?> cls) {
		this.point = point;
		this.cls = cls;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		if (Object.class.equals(method.getDeclaringClass())) {
			try {
				return method.invoke(this, args);
			} catch (Throwable t) {
				t.printStackTrace();
			}
		} else {
			return run(method, args);
		}
		return null;
	}

	public Object run(Method method1, Object[] args) throws NoSuchMethodException, SecurityException {
		Method method = cls.getMethod(method1.getName(), method1.getParameterTypes());
		Annotation a = method.getAnnotations()[0];
		RequestMapping rm = (RequestMapping) a;
		String url = rm.value()[0];
		ServicePoint sp = new ServicePoint();
		sp.setPoint(this.point);
		boolean opened = false;
		Parameter[] ps = method.getParameters();
		UrlInfo ui = new UrlInfo();
		for (int i = 0; i < ps.length; i++) {
			SessionAttribute sa = ps[i].getAnnotation(SessionAttribute.class);
			if (sa != null) {
				sp.open((String) args[i]);
				opened = true;
			}
			RequestParam rq = ps[i].getAnnotation(RequestParam.class);
			if (rq != null) {
				ui.add(rq.value(), (String) args[i]);
			}
		}
		ui.setRequestURL(url);

		String ret = sp.get(ui.toString());

		if (opened) {
			sp.close();
		}

		System.out.println(method.getReturnType().getName());

		ReturnList aa = method.getAnnotation(ReturnList.class);
		if (aa != null) {
			return JSON.parseArray(ret, aa.value());
		} else {
			return JSON.parseObject(ret, method.getReturnType());
		}
	}

}